아이템4
구조적 타이핑에 익숙해지기
타입스크립트 컴파일러의 역활
- 자바스크립트는 본질적으로
덕 타이핑(매개변수 값이 모두 제대로 주어진다면, 그 값이 어떻게 만들어졌는지 신경 쓰지 않고 사용) 기반이다.
interface Vector2D {
x: number;
y: number;
}
function calculateLength(v: Vector2D) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
- 위 예제서 name이 추가된 새 인터페이스가 생성되어도 타입스크립트에서 함수 호출이 가능하다.
interface NamedVector2D {
name: string;
x: number;
y: number;
}
function calculateLength(v: Vector2D) {
return Math.sqrt(v.x * v.x + v.y * v.y);
}
NamedVector2D와Vector2D의 관계를 전혀 선언하지 않았음에도 함수는 실행되었다.- 이유는 타입스크립트의 타입이 자바스크립트 런타임 동작에 모델링하기 떄문이고 이에 따라 둘의 구조가 호환되며 이를
구조적 타이핑이라 칭한다. - 다만 이로인해 문제가 발생하기도 한다.
interface Vector3D {
x: number;
y: number;
z: number;
}
function nomallize(v: Vector3D) {
return {x:v.x, y:v.y; z:v.z}
}
- 위와 같은 인터페이스가 존재할 때 z가 정규화 과정에서 무시되었고 타입 체커는 이 문제를 잡아내지 못한다.
- 이는 함수 작성시 호출에 사용되는 매개변수 속성들이 매개변수 타입에 선언된 속성만을 가질 것이라 생각하기 때문이다. 이러한 타입은
봉인된타입 또는정확한타입이라고 명명한다.
구조적 타이핑의 클래스에서의 문제
class C {
foo: string;
constructer(foo: string) {
this.foo = foo;
}
}
const c = new C("instace of C");
const d = { foo: "object literal" };
- d는
string타입의foo속성을 가지게 된다. 또한 호출이 되는 생성자를 가짐으로 문제가 생기지 않는다. 만일 C의 생성자에 단순 할당이 아닌 연산 로직이 존재한다면 d의 경우 문제가 발생한다.
요약
- 자바스크립트는 덕 타이핑이고 타입스크립트가 이를 모델링하기 떄문에 구조적 타이핑을 사용한다.
- 타입은 개방되어 있다.
- 클래스 역시 구조적 타이픙의 규칙을 따른다.
- 구조적 타이핑을 이용하면 유닛 테스를 쉽게 적용할 수 있다.